#include "netdetectionwidget.h"
#include <QNetworkAccessManager>
#include <QNetworkInformation>
#include <QNetworkReply>
#include <QTimer>
#include <QVBoxLayout>
#include "utils/util.h"
#include <utils/signalcenter.h>
NetDetectionWidget::NetDetectionWidget(QWidget *parent)
    : QWidget{parent}
    , detection(new QLabel())
    , label(new QLabel())
    , label2(new QLabel())
    , btnDetection(new LoadingButton(this))
    , networkconnected(true)
    , networkStatus(true)
    , checkNetworkconnectFinished(false)
    , tcpConnectStatus(false)
    , reloveDomainNameElasped(0)
    , stopCheck(false)
{
    QVBoxLayout *mainVLayout = new QVBoxLayout(this);
    mainVLayout->setObjectName("mainVLayout");
    mainVLayout->setContentsMargins(10, 10, 10, 10);
    mainVLayout->setAlignment(Qt::AlignCenter);
    mainVLayout->setSpacing(15);
    detection->setObjectName("detection");
    detection->setMinimumSize(QSize(200, 130));
    detection->setMaximumSize(QSize(200, 130));

    QPixmap pixmap(":/resources/NetworkDetection.png");
    pixmap.scaled(detection->size(), Qt::KeepAspectRatio);
    detection->setScaledContents(true);
    detection->setPixmap(pixmap);
    mainVLayout->addWidget(detection);

    label->setObjectName("label");
    label->setAlignment(Qt::AlignCenter);
    label->setText("网络检测");
    QFont font = label->font();
    setQFont(font, "Microsoft YaHei", 16, false);
    label->setFont(font);
    mainVLayout->addWidget(label);

    label->setObjectName("label2");
    label2->setAlignment(Qt::AlignCenter);
    label2->setText("请点击开始检测");
    QFont font2 = label2->font();
    setQFont(font2, "Microsoft YaHei", 10, false);
    label2->setFont(font2);
    label2->setStyleSheet("QLabel{color:gray;}");
    mainVLayout->addWidget(label2);

    QHBoxLayout *hboxLayout = new QHBoxLayout();
    hboxLayout->setObjectName("hboxLayout");
    hboxLayout->setAlignment(Qt::AlignCenter);
    btnDetection->setObjectName("btnDetection");
    btnDetection->setText("开始检测");
    btnDetection->setFont(font2);
    btnDetection->setMinimumSize(100, 30);
    btnDetection->setMaximumSize(100, 30);
    btnDetection->setStyleSheet(
        "QPushButton{background:rgb(0,111,255);color:white;border:none; border-radius:5px;}");
    hboxLayout->addWidget(btnDetection);

    mainVLayout->addLayout(hboxLayout);

    QLabel *spaceLabel = new QLabel();
    spaceLabel->setObjectName("spaceLabel");
    spaceLabel->setMinimumSize(QSize(170, 120));
    spaceLabel->setMaximumSize(QSize(170, 120));
    mainVLayout->addWidget(spaceLabel);

    connect(btnDetection, &QPushButton::clicked, this, &NetDetectionWidget::onbtnDetectionClick);
}

void NetDetectionWidget::onbtnDetectionClick()
{
    stopCheck = false;
    btnDetection->setText("");
    btnDetection->startLoading();
    label->setText("正在检测(1/5)");
    label2->setText("正在检测网络权限");

    //只能是使用线程来完成了，这个检查任务放到线程池中去执行，
    // checkNetworkConnected();
    QTimer::singleShot(500, this, &NetDetectionWidget::checkNetworkConnected);

    QTimer::singleShot(1000, this, &NetDetectionWidget::checkTcpServerConnected);

    QTimer::singleShot(1500, this, &NetDetectionWidget::resolveDomainName);

    QTimer::singleShot(2000, this, &NetDetectionWidget::TcpConnectCost);
}

void NetDetectionWidget::onStopCheck()
{
    btnDetection->stopLoading();
    stopCheck = true;
}

void NetDetectionWidget::checkNetworkConnected()
{
    //QNetworkAccessManager是QtNetwork模块中的一个核心类，
    //它允许应用程序发送网络请求并接收响应。该类是网络通信的基石，提供了一种方便的方式来处理常见的网络协议，
    //如HTTP、HTTPS等。
    //get()：发送一个GET请求到指定的URL。
    //post()：发送一个POST请求到指定的URL，并附带请求数据。
    //put()、upload()等：用于执行更复杂的网络操作，如文件上传等。

    label->setText("正在检测(2/5)");
    label2->setText("正在检测网络连接");

    //初始化 QNetworkAccessManager
    QNetworkAccessManager *manager = new QNetworkAccessManager(this);

    //向外部网站发送请求，用来测试网络连通性
    QNetworkRequest request(QUrl("http://www.baidu.com"));

    //发送HTTP get请求
    QNetworkReply *reply = manager->get(request);

    //使用信号来处理网络响应，这里的槽函数是异步执行的
    connect(reply, &QNetworkReply::finished, this, [this, reply]() {
        if (reply->error() == QNetworkReply::NoError) {
            qDebug() << "网络连接情况: 正常";
        } else {
            qDebug() << "网络连接情况: 异常 -" << reply->errorString();
            networkconnected = false;
        }
        reply->deleteLater();
    });
}

void NetDetectionWidget::checkTcpServerConnected()
{
    label->setText("正在检测(3/5)");
    label2->setText("正在检测服务器连接");
    socket = new QTcpSocket(this);
    qDebug() << "正在连接www.baidu.com, 端口:80";
    socket->connectToHost("36.152.44.96", 80);
    QElapsedTimer *timer = new QElapsedTimer();
    timer->start();
    connect(socket, &QTcpSocket::connected, this, [this, timer]() {
        tcpConnectElasped = timer->elapsed();
        qDebug() << "TCP连接成功，耗时:" << tcpConnectElasped << "ms";
        tcpConnectStatus = true;
    });

    connect(socket, &QTcpSocket::errorOccurred, this, [this](QAbstractSocket::SocketError error) {
        qDebug() << "连接失败，错误：" << error;
        tcpConnectElasped = QINT64_MAX;
        tcpConnectStatus = false;
    });
}

void NetDetectionWidget::resolveDomainName()
{
    label->setText("正在检测(4/5)");
    label2->setText("正在检测域名解析耗时");

    QString domainName = "www.baidu.com";
    //计算程序的运行时间可以使用QElapsedTimer 类。
    //QElapsedTimer 用于快速计算两个事件的间隔时间，它没有父类，不支持 Qt 的元对象系统， 所以只有接口函数。
    QElapsedTimer *timer = new QElapsedTimer();
    timer->start();
    QHostInfo::lookupHost(domainName, [this, timer](const QHostInfo &info) {
        qint64 elapsed = timer->elapsed();

        //检查是否解析成功
        if (info.error() == QHostInfo::NoError) {
            qDebug() << "解析成功，耗时:" << elapsed << "ms";
            //reloveDomainNameStatus = true;
            reloveDomainNameElasped = elapsed;
        } else {
            //reloveDomainNameStatus = false;
            reloveDomainNameElasped = QINT64_MAX;
        }

        delete timer;
    });
}

void NetDetectionWidget::TcpConnectCost()
{
    label->setText("正在检测(5/5)");
    label2->setText("正在测试连接耗时");
    btnDetection->stopLoading();
    qDebug() << stopCheck;

    if (!stopCheck) {
        emit checkNetworkFinished(networkStatus,
                                  networkconnected,
                                  tcpConnectStatus,
                                  tcpConnectElasped,
                                  reloveDomainNameElasped);
    }

    btnDetection->setText("开始测试");
    label->setText("网络检测");
    label2->setText("请点击开始检测");
}
